/**
 * @file ControladorJugador.java
 * Archivo que contiene la clase ControladorJugador.java
 * 
 * @author Carlos Rabelo
 * @version 2.2
 */

package Controladores;

import Interfaz.InterfazJugador;
import GestorJugadores.Jugador;
import GestorJugadores.JugadorBD;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Clase controlador que interactúa con la interfaz, recogiendo y enviando
 * datos de y a la interfaz acerca de los jugadores. Además gestiona los datos,
 * los valida e interactúa con la Base de Datos a través de la clase JugadorBD.
 * 
 * Se implementa siguiendo el patrón de Diseño "Singleton"
 * 
 * @author Carlos Rabelo
 * @version 2.2
 */
public class ControladorJugador {

    private static ControladorJugador Instancia=null;// = new JugadorBD();
    private Jugador[] jugadores;
    private int jugadorActivo;
    
    /**
     * Constructor por defecto. Al ser un singleton el contructor es privado
     * @param void
     * @return void
     */
    private ControladorJugador(){
        jugadores=null;
        jugadorActivo=-1;
    }
    
    /**
     * Método que devuelve la única instancia de la clase
     * @param void
     * @return Instancia
     */
    public static ControladorJugador getInstancia() {
        if (Instancia==null){
            Instancia = new ControladorJugador();
        }
        return Instancia;
    }

    @Override
    /**
     * Sobrecarga del método clone para impedir que se duplique la instancia
     * (Exigencias del patrón Singleton)
     * @param void
     * @return Object
     */
    public Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException(); 
    }
    
    /**
     * Método que inicializa el estado de la instancia
     * @param void
     * @return void
     */
    public void inicializar(){
        jugadorActivo=-1;
        jugadores=null;
    }
    
    /**
     * Método que recibe los datos de un Jugador como un vector de String
     * valida la corrección de los datos y, en caso de que sean correctos,
     * crea un objeto Jugador y lo envía a la clase JugadorBD para su
     * inclusión en la Base de Datos. Envía mensajes al usuario avisando del
     * éxito o fracaso de la operación.
     * @param Datos Vector de String
     * @return true si todo se hizo con éxito o false si hubo error bien sea
     * en la validación de datos, bien en el acceso a la Base de Datos.
     */
    public Boolean addJugador(String [] Datos){
        Jugador jug;
        //String [] Datos=InterfazJugador.getInstancia().cargarDatosFormulario();
        
        if ((jug=VerificarDatosCorrectosJugador(Datos))!=null){ // Datos correctos
            // Jugador válido, preparar la lista
            jugadores=new Jugador[1];
            // Enviar a la BD
            jugadores[0]=JugadorBD.getInstancia().addJugador(jug);
            if (jugadores[0]!=null){ // Jugador añadido con exito
                jugadorActivo=0;
                InterfazJugador.getInstancia().mostrarMensaje("Jugador añadido con éxito","OK", 1);
                return true;
            } else { // Error con la BD
                InterfazJugador.getInstancia().mostrarMensaje("Error al introducir el jugador en la Base de Datos.\nIntentelo de nuevo.", "Error en la Base de Datos", 0);
                return false;
            }
        } else {
            // Error con los datos
            InterfazJugador.getInstancia().mostrarMensaje("Error en los datos introducidos.", "Error", 0);
            return false;
        }
    }
    
    
    /**
     * Método que recibe como entrada una cadena Nombre y una cadena Apellidos
     * para buscar jugadores en la Base de Datos cuyos nombre y apellidos
     * comienzen por dichas cadenas.
     * En caso de error envía mensajes al usuario avisando fracaso de la operación.
     * En caso de éxito modifica la interfaz para mostrar los datos.
     * @param Nombre String
     * @param Apellidos String
     * @return true si se encontraron jugadores, false si no.
     */
    public Boolean getJugador(String [] datos){     

        String Nombre = datos[0]; 
        String Apellidos = datos[1];
        jugadores=JugadorBD.getInstancia().getJugador(Nombre, Apellidos);
        if (jugadores!=null){ // Se han encontrado jugadores
            jugadorActivo=0;
            if (jugadores.length>1){
                
                InterfazJugador.getInstancia().set_MostrarTabla(true);
                InterfazJugador.getInstancia().set_Filas_Tabla(jugadores.length);
                for (int i=0; i<jugadores.length; i++){
                    InterfazJugador.getInstancia().add_Jugador_Tabla(i, jugadores[i].getNombre(), jugadores[i].getApellidos());
                }
            } else {
                InterfazJugador.getInstancia().set_MostrarTabla(false);
            }
            InterfazJugador.getInstancia().mostrarJugador(
                    jugadores[jugadorActivo].getNombre(),
                    jugadores[jugadorActivo].getApellidos(),
                    jugadores[jugadorActivo].getSexo(),
                    jugadores[jugadorActivo].getNacimiento(),
                    jugadores[jugadorActivo].getTalla(),
                    jugadores[jugadorActivo].getTutor(),
                    jugadores[jugadorActivo].getCorreo(),
                    jugadores[jugadorActivo].getNumCuenta(),
                    jugadores[jugadorActivo].getTelefono(),
                    jugadores[jugadorActivo].getObservaciones(),
                    jugadores[jugadorActivo].getFormaPago(),
                    jugadores[jugadorActivo].getEstado()
                    );
            return true;
        } else { // No hay jugadores
            InterfazJugador.getInstancia().mostrarMensaje("No se han encontrado jugadores con los datos introducidos", "No hay datos", 1);
            return false;
        }
        
    }
    
    
    /**
     * Método que recibe los datos de un Jugador a modificar como un vector
     * de String valida la corrección de los datos y, en caso de que sean
     * correctos, los envía a la clase JugadorBD para su modificación en la
     * Base de Datos.
     * Envía mensajes al usuario avisando del éxito o fracaso de la operación.
     * @param Datos Vector de String
     * @return true si todo se hizo con éxito o false si hubo error bien sea
     * en la validación de datos, bien en el acceso a la Base de Datos.
     */
    public Boolean updateJugador(String [] Datos){
        Jugador jug;
        //String [] Datos=InterfazJugador.getInstancia().cargarDatosFormulario();
        
        if ((jug=VerificarDatosCorrectosJugador(Datos))!=null){ // Datos correctos
            // Se completa el nuevo Jugador jug con idJugador
            jug.setIdJugador(jugadores[jugadorActivo].getIdJugador());
            // Enviar a la BD
            if (JugadorBD.getInstancia().updateJugador(jug)){
                // Modificado con éxito
                jugadores[jugadorActivo]=jug;
                InterfazJugador.getInstancia().mostrarMensaje("Jugador modificado con éxito","OK", 1);
                return true;
            } else {
                InterfazJugador.getInstancia().mostrarMensaje("Error al modificar el jugador en la Base de Datos.\nIntentelo de nuevo.", "Error en la Base de Datos", 0);
                return false;
            }
        } else {
            // Error con los datos
            InterfazJugador.getInstancia().mostrarMensaje("Error en los datos introducidos.", "Error", 0);
            return false;
        }
    }
    
    
    /**
     * Método que modifica el estado del jugador activo y lo envía a JugadorBD
     * para su modificación en la Base de Datos vía.
     * Envía mensajes al usuario avisando del éxito o fracaso de la operación.
     * @param void
     * @return true si todo se hizo con éxito o false si hubo error en el
     * acceso a la Base de Datos.
     */
    public Boolean deleteJugador(){
        Boolean old_estado=jugadores[jugadorActivo].getEstado();
        jugadores[jugadorActivo].setEstado(false);
        if (JugadorBD.getInstancia().deleteJugador(jugadores[jugadorActivo].getIdJugador())){
            InterfazJugador.getInstancia().mostrarMensaje("Jugador borrado con éxito","OK", 1);
            return true;
        } else {
            jugadores[jugadorActivo].setEstado(old_estado);
            InterfazJugador.getInstancia().mostrarMensaje("Error al borrar el jugador en la Base de Datos.\nIntentelo de nuevo.", "Error en la Base de Datos", 0);
            return false;
        }
    }
    
    
    /**
     * Método que recibe los datos de un Jugador como un vector de String
     * valida la corrección de los datos y, en caso de que sean correctos,
     * crea un objeto Jugador y lo devuelve. Si los datos no son válidos
     * muestra información en la interfaz acerca de cuales son incorrectos.
     * @param Datos Vector de String
     * @return Un objeto Jugador y los datos son correctos o null si no.
     */
    public Jugador VerificarDatosCorrectosJugador(String [] Datos){
        // Si algo incorrecto avisar a la interfaz y mostrar mensaje
        Boolean error;
        
        Boolean nombre=false;
        Boolean apellidos=false;
        Boolean sexo=false;
        Boolean fecha=false;
        Boolean talla=false;
        Boolean tutor=false;
        Boolean correo=false;
        Boolean numcuenta=false;
        Boolean telefono=false;
        Boolean estadob=false;
        Boolean formapago=false;
        
        
        Boolean estadoc=true;
        Date fechan=null;
        Integer tel=0;
        
        if (Datos[0].length()==0 || Datos[0].length()>20) {
            nombre=true;
        }
        if (Datos[1].length()==0 || Datos[1].length()>40) {
            apellidos=true;
        }
        if (Datos[2]==null) {
            sexo=true;
        }
        //Fecha no comprobada
        SimpleDateFormat formatter = new SimpleDateFormat("DD-MM-yyyy");
        try {
            fechan = formatter.parse(Datos[3]);
        } catch (ParseException ex) {
            //Logger.getLogger(ControladorJugador.class.getName()).log(Level.SEVERE, null, ex);
        }
        //Talla no comprobada
        
        if (Datos[5].length()==0 || Datos[5].length()>60) {
            tutor=true;
        }
        if (Datos[6].length()==0 || Datos[6].length()>60) {
            correo=true;
        }
        if (Datos[7].length()!=20) {
            numcuenta=true;
        } else {
            try {
                Double.parseDouble(Datos[7]);
            } catch (NumberFormatException ex) {
                numcuenta = true;
            }
        }
        if (Datos[8].length()!=9) {
            telefono=true;
        } else {
            try {
                tel=Integer.parseInt(Datos[8]);
            } catch (NumberFormatException ex) {
                telefono = true;
            }
        }
        if (Datos[9]==null){
            estadob=true;
        } else if (Datos[9].equals("activo")){
            estadoc=true;
        } else {
            estadoc=false;
        }
        
        if (Datos[10]==null) {
            formapago=true;
        }
        
        error = (nombre || apellidos || sexo || fecha || talla || tutor || correo || numcuenta || telefono || estadob || formapago);
        if (error){
            InterfazJugador.getInstancia().marcarErrores(nombre, apellidos, sexo, fecha, talla, tutor, correo, numcuenta, telefono, estadob, formapago);
        } else {
            return new Jugador(Datos[0], Datos[1], Datos[2].charAt(0), fechan, Datos[4], Datos[5], Datos[6], Datos[7], tel, Datos[10],Datos[11].charAt(0), estadoc );
        }
        return null;
    }
 
    /**
     * Método que interactúa con la interfaz para mostrar datos. Recibe como
     * parámetro un entero indicando el jugador de los disponibles que se
     * quiere mostrar en la interfaz, lo selecciona como jugador activo y
     * lo muestra. Si recibe null no modifica el jugador activo pero refresca
     * sus datos en la interfaz. (Se usa esta opción, entre otros, al cancelar
     * una modificación parar restaurar los datos originales)
     * @param fila 
     * @return true si se muestra algún jugador en la interfaz y false si no
     */
    public Boolean refrescar(Integer fila){
        InterfazJugador.getInstancia().limpiarErrores();
        if (jugadorActivo==-1){
            //InterfazJugador.getInstancia().limpiar();
            return false;
        } else {
            if (fila!=null){
                jugadorActivo=fila;
            }
            InterfazJugador.getInstancia().mostrarJugador(jugadores[jugadorActivo].getNombre(),
                    jugadores[jugadorActivo].getApellidos(),
                    jugadores[jugadorActivo].getSexo(),
                    jugadores[jugadorActivo].getNacimiento(),
                    jugadores[jugadorActivo].getTalla(),
                    jugadores[jugadorActivo].getTutor(),
                    jugadores[jugadorActivo].getCorreo(),
                    jugadores[jugadorActivo].getNumCuenta(),
                    jugadores[jugadorActivo].getTelefono(),
                    jugadores[jugadorActivo].getObservaciones(),
                    jugadores[jugadorActivo].getFormaPago(),
                    jugadores[jugadorActivo].getEstado()
                    );
            return true;
        }
    }
}
